package cn.iocoder.yudao.module.trade.service.order;

import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderSummaryRespVO;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderDetailRespVO;
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
import cn.iocoder.yudao.module.trade.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND;

/**
 * 交易订单【读】 Service 实现类
 *
 * @author 芋道源码
 */
@Service
public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {

    @Resource
    private ExpressClientFactory expressClientFactory;

    @Resource
    private TradeOrderMapper tradeOrderMapper;
    @Resource
    private PayOrderApi payOrderApi;
    @Resource
    private TradeOrderDeliveryService deliveryService;
    @Resource
    private TradeOrderItemMapper tradeOrderItemMapper;

    @Resource
    private DeliveryExpressService deliveryExpressService;

    @Resource
    private MemberUserApi memberUserApi;

    // =================== Order ===================

    @Override
    public TradeOrderDO getOrder(Long userId, String id) {
        return tradeOrderMapper.selectOrderByNoAndUserId(id, userId);
    }


    private Set<Long> buildQueryConditionUserIds(TradeOrderPageReqVO reqVO) {
        // 获得 userId 相关的查询
        Set<Long> userIds = new HashSet<>();
//        if (StrUtil.isNotEmpty(reqVO.getUserMobile())) {
//            MemberUserRespDTO user = memberUserApi.getUserByMobile(reqVO.getUserMobile());
//            if (user == null) { // 没查询到用户，说明肯定也没他的订单
//                return null;
//            }
//            userIds.add(user.getId());
//        }
//        if (StrUtil.isNotEmpty(reqVO.getUserNickname())) {
//            List<MemberUserRespDTO> users = memberUserApi.getUserListByNickname(reqVO.getUserNickname());
//            if (CollUtil.isEmpty(users)) { // 没查询到用户，说明肯定也没他的订单
//                return null;
//            }
//            userIds.addAll(convertSet(users, MemberUserRespDTO::getId));
//        }
        return userIds;
    }

    @Override
    public TradeOrderSummaryRespVO getOrderSummary(String type) {
        if (Objects.equals(type, "3,4")) {
            Integer settle = tradeOrderMapper.getLockOrderSettle();
            return tradeOrderMapper.getLockOrderSummary().setSettledCount(settle);
        }
        return null;
    }

    @Override
    public PageResult<TradeOrderDO> getOrderPage(Long userId, TradeOrderPageReqVO reqVO) {
        return tradeOrderMapper.selectPage(reqVO, userId);
    }

    @Override
    public Long getOrderCount(Long userId, Integer status, Boolean commentStatus) {
//        return tradeOrderMapper.selectCountByUserIdAndStatus(userId, status, commentStatus);
        return null;
    }

    @Override
    public List<ExpressTrackRespDTO> getExpressTrackList(Long id, Long userId) {
        // 查询订单
//        TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId);
//        if (order == null) {
//            throw exception(ORDER_NOT_FOUND);
//        }
//        // 查询物流
//        return getExpressTrackList(order);
        return null;
    }

    @Override
    public List<ExpressTrackRespDTO> getExpressTrackList(Long id) {
        // 查询订单
        TradeOrderDO order = tradeOrderMapper.selectById(id);
        if (order == null) {
            throw exception(ORDER_NOT_FOUND);
        }
        // 查询物流
        return getExpressTrackList(order);
    }

    @Override
    public AppTradeOrderDetailRespVO getOrderDetial(String orderNo) {
        // 1.1 查询订单
        TradeOrderDO order = this.getOrder(getLoginUserId(), orderNo);
        if (order == null) {
            return null;
        }
        // 1.2 sync 仅在等待支付
//        if (Boolean.TRUE.equals(sync) && TradeOrderStatusEnum.isUnpaid(order.getStatus())) {
//            tradeOrderUpdateService.syncOrderPayStatusQuietly(order.orderNo(), order.getPayOrderId());
//            // 重新查询，因为同步后，可能会有变化
//            order = tradeOrderQueryService.getOrder(orderNo);
//        }

        // 2.1 查询订单支付
        PayOrderRespDTO payOrderRespDTO = payOrderApi.getOrder(order.getPayOrderId());
        AppTradeOrderDetailRespVO res = TradeOrderConvert.INSTANCE.convertDetail(order, payOrderRespDTO);
        List<TradeOrderDeliveryDO> deliveryS = deliveryService.queryByOrderNo(order.getOrderNo());
        for (TradeOrderDeliveryDO delivery : deliveryS) {
            if (DeliveryTypeEnum.EXPRESS_TO_MEMBER.getType().equals(delivery.getType())) {
                res.setMemberAddr(TradeOrderConvert.INSTANCE.convertDelivery(delivery));
            } else {
                res.setShopAddr(TradeOrderConvert.INSTANCE.convertDelivery(delivery));
            }
        }
        return res;
    }

    @Override
    public TradeOrderDO getOrderByPayOrderId(Long payOrderId) {
        return tradeOrderMapper.selectOne(TradeOrderDO::getPayOrderId, payOrderId);
    }

    @Override
    public Map<String, Object> getIndexNumber() {
        return tradeOrderMapper.getIndexNumber();
    }

    @Override
    public Map<String, Object> getIndexOrderNumber(Integer type) {
        // 默认当天
        LocalDateTime startTime = LocalDateTime.now();
        if (type == 1) { // 周一
            startTime = LocalDateTime.now().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        } else if (type ==2) { // 月1号
            startTime = LocalDateTime.now().with(TemporalAdjusters.firstDayOfMonth());
        } else if (type == 3) { // 年1号
            startTime = LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear());
        }
        startTime = startTime.toLocalDate().atStartOfDay();
        return tradeOrderMapper.getIndexOrderNumber(startTime);
    }

    @Override
    public List<TradeOrderDeliveryDO> getOrderDelivery(String orderNo, Integer type) {
        if (type != null) {
            return Collections.singletonList(deliveryService.queryByOrderNoAndType(orderNo, DeliveryTypeEnum.getEnum(type)));
        }
        return deliveryService.queryByOrderNo(orderNo);
    }

    @Override
    public BigDecimal queryWeightSumByTypeAndUser(Integer policyType, Long loginUserId) {
        return tradeOrderMapper.queryWeightSumByTypeAndUser(policyType, loginUserId);
    }

    /**
     * 获得订单的物流轨迹
     *
     * @param order 订单
     * @return 物流轨迹
     */
    private List<ExpressTrackRespDTO> getExpressTrackList(TradeOrderDO order) {
//        if (order.getLogisticsId() == null) {
//            return Collections.emptyList();
//        }
//        // 查询物流公司
//        DeliveryExpressDO express = deliveryExpressService.getDeliveryExpress(order.getLogisticsId());
//        if (express == null) {
//            throw exception(EXPRESS_NOT_EXISTS);
//        }
//        // 查询物流轨迹
//        return getSelf().getExpressTrackList(express.getCode(), order.getLogisticsNo(), order.getReceiverMobile());
        return null;
    }

    /**
     * 查询物流轨迹
     * <p>
     * 缓存的目的：考虑及时性要求不高，但是每次调用需要钱
     *
     * @param code           快递公司编码
     * @param logisticsNo    发货快递单号
     * @param receiverMobile 收、寄件人的电话号码
     * @return 物流轨迹
     */
    @Cacheable(cacheNames = RedisKeyConstants.EXPRESS_TRACK, key = "#code + '-' + #logisticsNo + '-' + #receiverMobile",
            unless = "#result == null")
    public List<ExpressTrackRespDTO> getExpressTrackList(String code, String logisticsNo, String receiverMobile) {
        return expressClientFactory.getDefaultExpressClient().getExpressTrackList(new ExpressTrackQueryReqDTO()
                .setExpressCode(code).setLogisticsNo(logisticsNo).setPhone(receiverMobile));
    }

    /**
     * 获得自身的代理对象，解决 AOP 生效问题
     *
     * @return 自己
     */
    private TradeOrderQueryServiceImpl getSelf() {
        return SpringUtil.getBean(getClass());
    }

}
